﻿// Decompiled with JetBrains decompiler
// Type: Microsoft.InfoCards.SafeCryptoKey
// Assembly: infocard, Version=3.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
// MVID: 8E14765A-6610-409A-BA36-099A0642905D
// Assembly location: E:\git\ALLIDA\windll\infocard.exe

using Microsoft.InfoCards.Diagnostics;
using System;
using System.ComponentModel;
using System.Runtime.InteropServices;
using System.Security;
using System.Security.Cryptography;

namespace Microsoft.InfoCards
{
  internal class SafeCryptoKey : IDisposable
  {
    private SafeCryptoKeyHandle m_handle;

    [SuppressUnmanagedCodeSecurity]
    [DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
    private static extern bool CryptSetKeyParam(
      [In] SafeCryptoKeyHandle hKey,
      [In] uint dwParam,
      [In] IntPtr data,
      [In] uint flags);

    [SuppressUnmanagedCodeSecurity]
    [DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
    private static extern bool CryptImportKey(
      [In] SafeRsaProviderHandle hProv,
      [In] IntPtr pbKeyData,
      [In] uint dwDataLen,
      [In] IntPtr hPubKey,
      [In] uint dwFlags,
      out SafeCryptoKeyHandle hKey);

    public SafeCryptoKeyHandle Handle
    {
      get
      {
        return this.m_handle;
      }
    }

    public unsafe SafeCryptoKey(SafeRsaProviderHandle provider, byte[] encryptedKey, byte[] iv)
    {
      SafeCryptoKey.BlobHeader blobHeader = new SafeCryptoKey.BlobHeader(encryptedKey.Length);
      int num = sizeof (SafeCryptoKey.BlobHeader) + encryptedKey.Length;
      // ISSUE: untyped stack allocation
      byte* numPtr1 = (byte*) __untypedstackalloc(num);
      byte* numPtr2 = (byte*) &blobHeader;
      for (int index = 0; index < 12; ++index)
        numPtr1[index] = numPtr2[index];
      try
      {
        ProtectedMemory.Unprotect(encryptedKey, MemoryProtectionScope.SameProcess);
        for (int index = 0; index < encryptedKey.Length; ++index)
          numPtr1[12 + index] = encryptedKey[index];
      }
      finally
      {
        ProtectedMemory.Protect(encryptedKey, MemoryProtectionScope.SameProcess);
      }
      if (!SafeCryptoKey.CryptImportKey(provider, (IntPtr) ((void*) numPtr1), (uint) num, IntPtr.Zero, 0U, out this.m_handle))
      {
        Exception e = (Exception) new Win32Exception(Marshal.GetLastWin32Error());
        InfoCardTrace.CloseInvalidOutSafeHandle((SafeHandle) this.m_handle);
        InfoCardTrace.TraceAndLogException(e);
        throw InfoCardTrace.ThrowHelperError(e);
      }
      fixed (byte* numPtr3 = &iv[0])
      {
        if (!SafeCryptoKey.CryptSetKeyParam(this.m_handle, 1U, (IntPtr) ((void*) numPtr3), 0U))
        {
          Exception e = (Exception) new Win32Exception(Marshal.GetLastWin32Error());
          this.m_handle.Dispose();
          throw InfoCardTrace.ThrowHelperError(e);
        }
        // ISSUE: __unpin statement
        __unpin(numPtr3);
      }
    }

    void IDisposable.Dispose()
    {
      this.m_handle.Dispose();
    }

    [StructLayout(LayoutKind.Explicit, Size = 12)]
    private struct BlobHeader
    {
      private const int PLAINTEXTKEYBLOB = 8;
      private const int CUR_BLOB_VERSION = 2;
      private const int CALG_AES = 26128;
      [FieldOffset(0)]
      public byte bType;
      [FieldOffset(1)]
      public byte bVersion;
      [FieldOffset(2)]
      public ushort reserved;
      [FieldOffset(4)]
      public uint aiKeyAlg;
      [FieldOffset(8)]
      public uint keyLength;

      public BlobHeader(int keySize)
      {
        this.bType = (byte) 8;
        this.bVersion = (byte) 2;
        this.reserved = (ushort) 0;
        this.aiKeyAlg = 26128U;
        this.keyLength = (uint) keySize;
      }
    }
  }
}
